<?php

use Base\BaseController;
use Illuminate\Support\Str;
use JetBrains\PhpStorm\NoReturn;
use Jwt\Token;
use Cache\Redis;
use Yaf\Application;

class IndexController extends BaseController
{
    /**
     * 管理后台首页登录
     * @return void
     */
    #[NoReturn] public function loginAction(): void
    {
        if (!Request::instance()->isPost()) $this->apiError("请求方式错误",10000);
        try {
            $info = $this->loginCheck();
            Token::$prefix_refresh = "admin_refresh_token:";
            Token::$prefix_member = "admin_member_token:";
            $token = Token::generate(['id' => $info['id'], 'nickname' => $info['nickname'], 'mobile' => $info['mobile']]);
            if ($token===false) $this->apiError("登录失败",10000);
            $roleIds = $info->role->pluck("role_id")->toArray();
            $permission_id = RoleHasPermissionModel::query()->whereIn("role_id",$roleIds)->get()->pluck("permission_id");
            $permission_mark = PermissionModel::query()->whereIn("id",$permission_id)->get()->pluck("permission_mark")->toArray();
            Redis::getRedis()->set("backendPermissions-".$info->uuid,$permission_mark);
            $this->apiSuccess($token,'登录成功',20000);
        } catch (Exception $exception) {
            Log::$customFileName = LOG_PATH."/errors/";
            Log::error($exception->getMessage().$exception->getTraceAsString());
            $this->apiError($exception->getMessage());
        }
    }

    /**
     * 登录检测验证
     * @return object|null
     */
    protected function loginCheck(): object|null
    {
        $captcha = new Captcha();
        $info =UserModel::query()
            ->with(["role"])
            ->where("username", Request::input("username"))
            ->selectRaw("uuid,id,nickname,username,mobile,password,salt,login_time,login_ip,is_hid")
            ->first();
        if (!$info) {
            $log['status'] = "error";
            $log['error_message'] = '账号不存在';
            LoginLogModel::insert($log);
            $this->apiError("账号不存在",10000);
        }
        $log = [
            'uuid'=> (string)Str::uuid(),
            'user_id'=>$info['id'],
            'username'=>$info['username'],
            'browser_type'=>getBrowser(),
            'data'=>json_encode(Request::all()),
            'system_type'=>getOs(),
            'login_ip'=>get_client_ip(),
            'created_at'=>date("Y-m-d H:i:s"),
            'ip_address'=>getIpAddress()['address']??""
        ];
        $password = openssl_decrypt(base64_decode(Request::input('password')),
            'AES-256-CBC', Application::app()->getConfig()->application->passphrase,
            OPENSSL_RAW_DATA, Application::app()->getConfig()->application->iv);
        if(!$captcha->verify(Request::input('captchaCode'),Request::input('captchaKey'))){
            $this->apiError("验证码错误",10000);
        }
        if (!password_verify( $password.$info['salt'],$info['password'])){
            $log['status'] = "error";
            $log['error_message'] = '密码错误';
            LoginLogModel::insert($log);
            $this->apiError("密码错误",10000);
        }
        if ($info['is_hid']==1) {
            $log['status'] = "error";
            $log['error_message'] = '账号被禁用';
            LoginLogModel::insert($log);
            $this->apiError("账号被禁用，请联系管理员",10000);
        }
        UserModel::where('id',$info['id'])->update([
                'login_time'=>date("Y-m-d H:i:s"),
                'login_ip'=>get_client_ip(),
                'last_login_ip'=>$info['login_ip'],
                'last_login_time'=>$info['login_time']
            ]);
        $log['status'] = "success";
        LoginLogModel::insert($log);
        return $info;
    }

    /**
     * 获取图形验证码
     * @return void
     * @throws Exception
     */
    public function captchaAction():void
    {
        try {
            $captcha = new Captcha();
            $data = $captcha->getCode();
            $this->apiSuccess($data,"获取成功",20000);
        }catch (Exception $exception) {
            Log::$customFileName = LOG_PATH."/errors/";
            Log::error($exception->getMessage().$exception->getTraceAsString());
            $this->apiError($exception->getMessage());
        }
    }
}
